<?php
/***************************************************************
*  Copyright notice
*  (c) 2009, jianyuzhu@gmail.com
*  All rights reserved
*  This script is part of the PPEMI project.
***************************************************************/

class CoreCacheFile extends CoreCache {
	var $cache_expiry = 3600;
	var $cache_success = false;
	var $cache_dir = '';
	var $cache_sub_dirs = true;
	
	//constructor
	function CoreCacheFile($cache_dir = 'datacache', $cache_expiry = 3600) {
		parent::CoreCache();
		//
		$this->cache_dir = CONFIG_PATH . CONFIG_DIR_CACHE . $cache_dir;
		$this->cache_expiry = $cache_expiry;
		$this->cache_success = false;
	}
	
	//methods
	function setKP($kp) {
		$this->kp = $kp;
	}
	
	//call
	function call() {
		$args = func_get_args();
		$obj = $args['0'];
		$method = $args['1'];
		$params = array();
		if( isset($args['2']) ) {
			$params = $args['2'];
			if( !is_array($params) ) {
				$params = array($params);
			}
		}
		
		$prefix = $obj . '_' . $method;
		$key = $this->_get_array_key($params);
		$data = $this->get($key, $prefix);
		if( $this->cache_success == true ) {
			$this->cache_success = false;
		} else {
			global $$obj;
			if( is_object($$obj) ) {
				if( sizeof($params) == 0 ) {
					$data = $$obj->$method();
				} elseif( sizeof($params) == 1 ) {
					$data = $$obj->$method($params['0']);
				} elseif( sizeof($params) == 2 ) {
					$data = $$obj->$method($params['0'], $params['1']);
				} elseif( sizeof($params) == 3 ) {
					$data = $$obj->$method($params['0'], $params['1'], $params['2']);
				} else {
					$data = $$obj->$method($params['0'], $params['1'], $params['2'], $params['3']);
				}
			}
			
			$this->set($key, $data, $prefix);
		}
		
		return $data;
	}
	
	function get($key, $prefix) {
		$result = false;
		$hash_key = $this->_get_hash_key($key);
		if( $this->cache_sub_dirs == true ) {
			$cdir = $this->cache_dir . '/' . $this->kp . '_' . $prefix . '/';
			if( !is_dir($cdir) ) {
				@mkdir($cdir);
			}
			$cache_file = $cdir . $hash_key . '.php';
		} else {
			$cache_file = $this->cache_dir . '/' . $this->kp . '_' . $prefix . '_' . $hash_key . '.php';
		}
		
		if( is_file($cache_file) && ($data=file_get_contents($cache_file)) && isset($data['23']) ) {
			$filetime = substr($data, 13, 10);
			$data = substr($data, 23);
			if( $filetime < time() - $this->cache_expiry ) {
				@unlink($cache_file);
			} else {
				$result = unserialize($data);
				$this->cache_success = true;
			}
		}
		
		return $result;
	}
	
	function getT($key, $prefix, $cache_expiry = '') {
		$result = false;
		$hash_key = $this->_get_hash_key($key);
		if( $this->cache_sub_dirs == true ) {
			$cdir = $this->cache_dir . '/' . $this->kp . '_' . $prefix . '/';
			if( !is_dir($cdir) ) {
				@mkdir($cdir);
			}
			$cache_file = $cdir . $hash_key . '.php';
		} else {
			$cache_file = $this->cache_dir . '/' . $this->kp . '_' . $prefix . '_' . $hash_key . '.php';
		}
		
		if( is_file($cache_file) && ($data=file_get_contents($cache_file)) && isset($data['23']) ) {
			$filetime = substr($data, 13, 10);
			$data = substr($data, 23);
			if( $cache_expiry == '' || $cache_expiry < 600 ) {
				$cache_expiry = $this->cache_expiry;
			}
			if( $filetime < time() - $cache_expiry ) {
				@unlink($cache_file);
			} else {
				$result = unserialize($data);
				$this->cache_success = true;
			}
		}
		
		return $result;
	}
	
	function set($key, $data, $prefix) {
		$success = false;
		$hash_key = $this->_get_hash_key($key);
		if( $this->cache_sub_dirs == true ) {
			$cdir = $this->cache_dir . '/' . $this->kp . '_' . $prefix . '/';
			if( !is_dir($cdir) ) {
				@mkdir($cdir);
			}
			$cache_file = $cdir . $hash_key . '.php';
		} else {
			$cache_file = $this->cache_dir . '/' . $this->kp . '_' . $prefix . '_' . $hash_key . '.php';
		}
		
		// try to open the file
		if( $fp = @fopen($cache_file, 'w')) {
			// obtain a file lock to stop corruptions occuring
			flock($fp, 2); // LOCK_EX
			// write serialized data
			fputs($fp, '<?php exit;?>' . time() . serialize($data));
			// release the file lock
			flock($fp, 3); // LOCK_UN
			fclose($fp);
			//
			//clearstatcache();
			//
			$success = true;
		}
		
		return $success;
	}
	
	//
	function clean($prefix) {
		include_once(CONFIG_PATH . CONFIG_DIR_CLASSES . 'core.directory.class.php');
		$dp = new CoreDirectoryParser($this->cache_dir);
		$dp->parse();
		//
		$files = $dp->getFiles($this->kp . '_' . $prefix);
		$dp->delete($files);
		//
		if( $this->cache_sub_dirs == true ) {
			$dirs = $dp->getDirs(array('p' => $this->kp . '_' . $prefix));
			$dp->clean($dirs);
		}
	}
	
	//
	function _get_hash_key($key) {
		return abs(crc32($key)) . '_' . md5($key);
	}
	
	function _get_array_key($data_array) {
		$key = '';
		if( is_array($data_array) ) {
			foreach($data_array as $k => $v) {
				if( is_array($v) ) {
					$key .= $k . '-' . $this->_get_array_key($v);
				} elseif( is_object($v) ) {
					$key .= $k . '-' . $this->_get_obj_key($v);
				} else {
					$key .= $k . '-' . $v . '--';
				}
			}
		} else {
			$key .= $data_array;
		}
		
		return $key;
	}
	
	function _get_obj_key($obj, $excludes = '') {
		if( is_object($obj) ) {
			$data_array = get_object_vars($obj);
			if( $excludes != '' ) {
				if( !is_array($excludes) ) {
					$excludes = array($excludes);
				}
				if( is_array($excludes) ) {
					if( is_array($data_array) ) {
						foreach($data_array as $k => $v) {
							if( in_array($k, $excludes) ) {
								unset($data_array[$k]);
							}
						}
					}
				}
			}
			
			return $this->_get_array_key($data_array);
		}
		
		return $obj;
	}
}
//
?>